﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using CSW.Framework.Common;

namespace CSW.Framework.UI
{
    /// <summary>
    /// Export Utils.
    /// </summary>
    public static class ExportUtils
    {
        /// <summary>
        /// Export a DataTable to a CSV file.
        /// </summary>
        /// <param name="dataTable">DataTable to export</param>
        /// <param name="path">Path to save CSV file</param>
        /// <param name="useQuotes">Use quotes around field values</param>
        /// <param name="includeHeaders">Include column headers in CSV file</param>
        /// <param name="showConfirmation">Show file saved dialog</param>
        /// <param name="autoLaunch">Automatically open CSV file</param>
        /// <param name="warnOnError">if set to <c>true</c> then warn on errors.</param>
        /// <returns>Returns true if file saved successfully</returns>
        public static bool CreateCSV(DataTable dataTable, string path, bool useQuotes, bool includeHeaders, bool showConfirmation, bool autoLaunch, bool warnOnError)
        {
            return CreateCSV(dataTable, path, useQuotes, includeHeaders, showConfirmation, autoLaunch, warnOnError, null);
        }

        /// <summary>
        /// Export a DataTable to a CSV file.
        /// </summary>
        /// <param name="dataTable">DataTable to export</param>
        /// <param name="path">Path to save CSV file</param>
        /// <param name="useQuotes">Use quotes around field values</param>
        /// <param name="includeHeaders">Include column headers in CSV file</param>
        /// <param name="showConfirmation">Show file saved dialog</param>
        /// <param name="autoLaunch">Automatically open CSV file</param>
        /// <param name="warnOnError">if set to <c>true</c> then warn on errors.</param>
        /// <param name="columnNames">The column names to export. (null = all columns).</param>
        /// <returns>Returns true if file saved successfully</returns>
        public static bool CreateCSV(DataTable dataTable, string path, bool useQuotes, bool includeHeaders, bool showConfirmation, bool autoLaunch, bool warnOnError, ICollection<string> columnNames)
        {
            Guard.ArgumentNotNull(dataTable, "dataTable");
            Guard.ArgumentNotNullOrEmptyString(path, "path");

            if (columnNames == null || columnNames.Count == 0)
            {
                columnNames = new List<string>();
                foreach (DataColumn dataColumn in dataTable.Columns)
                    columnNames.Add(dataColumn.ColumnName);
            }

            StreamWriter streamWriter = null;

            do
            {
                try
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(path));
                    streamWriter = new StreamWriter(path);
                }
                catch
                {
                    if (warnOnError)
                    {
                        DialogResult res = MessageBox.Show(string.Format("File \"{0}\" cannot be saved.\n\nYou may have the file open, or the file may be write protected.", path), "Save file", MessageBoxButtons.RetryCancel, MessageBoxIcon.Exclamation);
                        if (res != DialogResult.Retry)
                            return false;
                    }
                    else
                    {
                        throw new Exception(string.Format("File \"{0}\" cannot be saved.", path));
                    }
                }
            } while (streamWriter == null);

            try
            {
                bool isFirstColumn;
                string quote = "";

                if (useQuotes)
                    quote = "\"";

                if (includeHeaders)
                {
                    isFirstColumn = true;
                    foreach (string columnName in columnNames)
                    {
                        string value = dataTable.Columns[columnName].ColumnName;
                        if (!useQuotes)
                            value = value.Replace(",", "");

                        streamWriter.Write((!isFirstColumn ? "," : "") + quote + value + quote);
                        isFirstColumn = false;
                    }
                    streamWriter.WriteLine();
                }

                foreach (DataRow dr in dataTable.Rows)
                {
                    isFirstColumn = true;
                    foreach (string columnName in columnNames)
                    {
                        string value = dr[columnName].ToString().Replace(quote, quote + quote);
                        if (!useQuotes)
                            value = value.Replace(",", "");

                        streamWriter.Write((!isFirstColumn ? "," : "") + quote + value + quote);
                        isFirstColumn = false;
                    }
                    streamWriter.WriteLine();
                }
            }
            finally
            {
                streamWriter.Dispose();
            }

            if (autoLaunch)
            {
                try
                {
                    Process.Start(path);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("Error opening \"{0}\"", path), ex);
                }
            }

            if (showConfirmation)
                MessageBox.Show(string.Format("{0} saved.", path), "File saved", MessageBoxButtons.OK, MessageBoxIcon.Information);

            return true;
        }
    }
}
